package cn.iocoder.yudao.module.eval.controller.admin.assignment;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.module.eval.controller.admin.assignment.vo.*;
import cn.iocoder.yudao.module.eval.dal.dataobject.assignment.EvalPersonnelAssignmentDO;
import cn.iocoder.yudao.module.eval.service.assignment.EvalAssignmentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;

@Tag(name = "管理后台 - 人员分配管理")
@RestController
@RequestMapping("/eval/assignment")
@Validated
@Slf4j
public class EvalAssignmentController {

    @Resource
    private EvalAssignmentService assignmentService;

    @GetMapping("/evaluators/available")
    @Operation(summary = "查询可用考评员")
    @Parameter(name = "professionCode", description = "职业代码", required = false)
    @Parameter(name = "skillLevels", description = "技能等级", required = false)
    @Parameter(name = "planId", description = "计划ID", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<List<EvalAvailableEvaluatorRespVO>> getAvailableEvaluators(
            @RequestParam(value = "professionCode", required = false) String professionCode,
            @RequestParam(value = "skillLevels", required = false) String skillLevels,
            @RequestParam(value = "planId", required = false) Long planId) {
        List<EvalAvailableEvaluatorRespVO> list = assignmentService.getAvailableEvaluators(professionCode, skillLevels, planId);
        return success(list);
    }

    @GetMapping("/supervisors/available")
    @Operation(summary = "查询可用督导员")
    @Parameter(name = "planId", description = "计划ID", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<List<EvalAvailableSupervisorRespVO>> getAvailableSupervisors(
            @RequestParam(value = "planId", required = false) Long planId) {
        List<EvalAvailableSupervisorRespVO> list = assignmentService.getAvailableSupervisors(planId);
        return success(list);
    }

    @PostMapping("/evaluators/assign")
    @Operation(summary = "分配考评员")
    @PreAuthorize("@ss.hasPermission('eval:assignment:assign')")
    @ApiAccessLog(operateType = CREATE)
    public CommonResult<Boolean> assignEvaluators(@Valid @RequestBody EvalEvaluatorAssignmentReqVO assignmentReqVO) {
        assignmentService.assignEvaluators(assignmentReqVO);
        return success(true);
    }

    @PostMapping("/supervisors/assign")
    @Operation(summary = "分配督导员")
    @PreAuthorize("@ss.hasPermission('eval:assignment:assign')")
    @ApiAccessLog(operateType = CREATE)
    public CommonResult<Boolean> assignSupervisors(@Valid @RequestBody EvalSupervisorAssignmentReqVO assignmentReqVO) {
        assignmentService.assignSupervisors(assignmentReqVO);
        return success(true);
    }

    @GetMapping("/plan/{planId}")
    @Operation(summary = "查询计划的人员分配")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @Parameter(name = "personType", description = "人员类型：1-考评员，2-督导员", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<List<EvalPersonnelAssignmentRespVO>> getPlanAssignments(
            @PathVariable("planId") Long planId,
            @RequestParam(value = "personType", required = false) Integer personType) {
        List<EvalPersonnelAssignmentDO> list = assignmentService.getPlanAssignments(planId, personType);
        return success(BeanUtils.toBean(list, EvalPersonnelAssignmentRespVO.class));
    }

    @GetMapping("/plan/{planId}/page")
    @Operation(summary = "分页查询计划的人员分配")
    @Parameter(name = "planId", description = "计划ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<PageResult<EvalPersonnelAssignmentRespVO>> getPlanAssignmentPage(
            @PathVariable("planId") Long planId,
            @Valid EvalPersonnelAssignmentPageReqVO pageReqVO) {
        pageReqVO.setPlanId(planId);
        PageResult<EvalPersonnelAssignmentDO> pageResult = assignmentService.getAssignmentPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, EvalPersonnelAssignmentRespVO.class));
    }

    @PostMapping("/{assignmentId}/confirm")
    @Operation(summary = "确认任务分配")
    @Parameter(name = "assignmentId", description = "分配ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:assignment:confirm')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> confirmAssignment(@PathVariable("assignmentId") Long assignmentId,
                                                   @Valid @RequestBody EvalAssignmentConfirmReqVO confirmReqVO) {
        assignmentService.confirmAssignment(assignmentId, confirmReqVO.getConfirmStatus(), confirmReqVO.getConfirmComments());
        return success(true);
    }

    @PutMapping("/{assignmentId}/replace")
    @Operation(summary = "替换人员")
    @Parameter(name = "assignmentId", description = "分配ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:assignment:replace')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> replacePersonnel(@PathVariable("assignmentId") Long assignmentId,
                                                  @Valid @RequestBody EvalAssignmentReplaceReqVO replaceReqVO) {
        assignmentService.replacePersonnel(assignmentId, replaceReqVO.getNewUserId(), replaceReqVO.getReason());
        return success(true);
    }

    @DeleteMapping("/{assignmentId}")
    @Operation(summary = "取消人员分配")
    @Parameter(name = "assignmentId", description = "分配ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:assignment:cancel')")
    @ApiAccessLog(operateType = DELETE)
    public CommonResult<Boolean> cancelAssignment(@PathVariable("assignmentId") Long assignmentId,
                                                  @RequestParam(value = "reason", required = false) String reason) {
        assignmentService.cancelAssignment(assignmentId, reason);
        return success(true);
    }

    @GetMapping("/evaluator/{userId}/workload")
    @Operation(summary = "查询考评员工作量")
    @Parameter(name = "userId", description = "用户ID", required = true)
    @Parameter(name = "startDate", description = "开始日期", required = false)
    @Parameter(name = "endDate", description = "结束日期", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<EvalEvaluatorWorkloadRespVO> getEvaluatorWorkload(
            @PathVariable("userId") Long userId,
            @RequestParam(value = "startDate", required = false) String startDate,
            @RequestParam(value = "endDate", required = false) String endDate) {
        EvalEvaluatorWorkloadRespVO workload = assignmentService.getEvaluatorWorkload(userId, startDate, endDate);
        return success(workload);
    }

    @GetMapping("/supervisor/{userId}/schedule")
    @Operation(summary = "查询督导员工作安排")
    @Parameter(name = "userId", description = "用户ID", required = true)
    @Parameter(name = "startDate", description = "开始日期", required = false)
    @Parameter(name = "endDate", description = "结束日期", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<List<EvalSupervisorScheduleRespVO>> getSupervisorSchedule(
            @PathVariable("userId") Long userId,
            @RequestParam(value = "startDate", required = false) String startDate,
            @RequestParam(value = "endDate", required = false) String endDate) {
        List<EvalSupervisorScheduleRespVO> schedule = assignmentService.getSupervisorSchedule(userId, startDate, endDate);
        return success(schedule);
    }

    @GetMapping("/statistics")
    @Operation(summary = "人员分配统计")
    @Parameter(name = "planId", description = "计划ID", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<EvalAssignmentStatisticsRespVO> getAssignmentStatistics(
            @RequestParam(value = "planId", required = false) Long planId) {
        EvalAssignmentStatisticsRespVO statistics = assignmentService.getAssignmentStatistics(planId);
        return success(statistics);
    }

    @PostMapping("/batch-assign")
    @Operation(summary = "批量分配人员")
    @PreAuthorize("@ss.hasPermission('eval:assignment:assign')")
    @ApiAccessLog(operateType = CREATE)
    public CommonResult<Boolean> batchAssignPersonnel(@Valid @RequestBody EvalBatchAssignmentReqVO batchAssignReqVO) {
        assignmentService.batchAssignPersonnel(batchAssignReqVO);
        return success(true);
    }

    @PostMapping("/auto-assign")
    @Operation(summary = "智能分配人员")
    @PreAuthorize("@ss.hasPermission('eval:assignment:assign')")
    @ApiAccessLog(operateType = CREATE)
    public CommonResult<EvalAutoAssignmentResultRespVO> autoAssignPersonnel(@Valid @RequestBody EvalAutoAssignmentReqVO autoAssignReqVO) {
        EvalAutoAssignmentResultRespVO result = assignmentService.autoAssignPersonnel(autoAssignReqVO);
        return success(result);
    }

    @GetMapping("/conflicts")
    @Operation(summary = "检查分配冲突")
    @Parameter(name = "planId", description = "计划ID", required = false)
    @Parameter(name = "userId", description = "用户ID", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<List<EvalAssignmentConflictRespVO>> checkAssignmentConflicts(
            @RequestParam(value = "planId", required = false) Long planId,
            @RequestParam(value = "userId", required = false) Long userId) {
        List<EvalAssignmentConflictRespVO> conflicts = assignmentService.checkAssignmentConflicts(planId, userId);
        return success(conflicts);
    }

    @PostMapping("/notify")
    @Operation(summary = "发送分配通知")
    @PreAuthorize("@ss.hasPermission('eval:assignment:notify')")
    @ApiAccessLog(operateType = OTHER)
    public CommonResult<Boolean> sendAssignmentNotification(@Valid @RequestBody EvalAssignmentNotificationReqVO notificationReqVO) {
        assignmentService.sendAssignmentNotification(notificationReqVO);
        return success(true);
    }

    @GetMapping("/my-assignments")
    @Operation(summary = "我的分配任务")
    @Parameter(name = "status", description = "任务状态", required = false)
    @PreAuthorize("@ss.hasPermission('eval:assignment:query')")
    public CommonResult<List<EvalPersonnelAssignmentRespVO>> getMyAssignments(
            @RequestParam(value = "status", required = false) Integer status) {
        List<EvalPersonnelAssignmentDO> list = assignmentService.getMyAssignments(status);
        return success(BeanUtils.toBean(list, EvalPersonnelAssignmentRespVO.class));
    }

    @PostMapping("/my-assignments/{assignmentId}/accept")
    @Operation(summary = "接受分配任务")
    @Parameter(name = "assignmentId", description = "分配ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:assignment:accept')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> acceptAssignment(@PathVariable("assignmentId") Long assignmentId,
                                                  @RequestParam(value = "comments", required = false) String comments) {
        assignmentService.acceptAssignment(assignmentId, comments);
        return success(true);
    }

    @PostMapping("/my-assignments/{assignmentId}/reject")
    @Operation(summary = "拒绝分配任务")
    @Parameter(name = "assignmentId", description = "分配ID", required = true)
    @PreAuthorize("@ss.hasPermission('eval:assignment:reject')")
    @ApiAccessLog(operateType = UPDATE)
    public CommonResult<Boolean> rejectAssignment(@PathVariable("assignmentId") Long assignmentId,
                                                  @RequestParam("reason") String reason) {
        assignmentService.rejectAssignment(assignmentId, reason);
        return success(true);
    }

}
